package com.indusfo.spc.client.service.impl;

import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.QueryException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.indusfo.spc.client.mapper.ClientAnoDetailMapper;
import com.indusfo.spc.client.mapper.ClientAnoMapper;
import com.indusfo.spc.client.mapper.ClientBatchFlowFinishMapper;
import com.indusfo.spc.client.mapper.ClientBatchMapper;
import com.indusfo.spc.client.mapper.ClientMatMapper;
import com.indusfo.spc.client.mapper.ClientOrderBadphenoMapper;
import com.indusfo.spc.client.mapper.ClientOrderBomMapper;
import com.indusfo.spc.client.mapper.ClientOrderDeteMapper;
import com.indusfo.spc.client.mapper.ClientOrderFlowMapper;
import com.indusfo.spc.client.mapper.ClientOrderMapper;
import com.indusfo.spc.client.mapper.ClientOrderStationMapper;
import com.indusfo.spc.client.mapper.ClientPalletMapper;
import com.indusfo.spc.client.mapper.ClientProMapper;
import com.indusfo.spc.client.mapper.ClientRepairMapper;
import com.indusfo.spc.client.pojo.ClientAno;
import com.indusfo.spc.client.pojo.ClientRepair;
import com.indusfo.spc.client.service.ClientRepairService;
import com.indusfo.spc.common.pojo.BasePojo;
import com.indusfo.spc.exception.BusinessException;
import com.indusfo.spc.exception.ModifyFailedException;
import com.indusfo.spc.exception.ParamsErrorException;
import com.indusfo.spc.mapper.OrderMapper;
import com.indusfo.spc.pojo.Batch;
import com.indusfo.spc.pojo.BatchFlowFinish;
import com.indusfo.spc.pojo.Order;
import com.indusfo.spc.pojo.OrderFlow;

/**
 * 客户端返修
 * 
 * @author zhengd
 */
@Service
public class ClientRepairServiceImpl implements ClientRepairService {
	@Autowired
	private ClientAnoDetailMapper clientAnoDetailMapper;
	@Autowired
	private ClientOrderFlowMapper clientOrderFlowMapper;
	@Autowired
	private ClientAnoServiceImpl clientAnoServiceImpl;
	@Resource
	private ClientOrderStationMapper clientOrderStationMapper;
	@Resource
	private ClientOrderDeteMapper clientOrderDeteMapper;
	@Resource
	private ClientOrderBomMapper clientOrderBomMapper;
	@Resource
	private ClientOrderBadphenoMapper clientOrderBadphenoMapper;
	@Resource
	private ClientBatchFlowFinishMapper clientBatchFlowFinishMapper;
	@Resource
	private ClientRepairMapper clientRepairMapper;
	@Resource
	private ClientBatchMapper clientBatchMapper;
	@Resource
	private ClientProMapper clientProMapper;
	@Resource
	private ClientAnoMapper clientAnoMapper;
	@Resource
	private ClientMatMapper clientMatMapper;
	@Resource
	private ClientOrderMapper clientOrderMapper;
	@Resource
	private OrderMapper orderMapper;
	@Resource
	private ClientPalletMapper clientPalletMapper;

	/**
	 * 扫码进站及查询返修基础信息
	 */
	@Override
	@Transactional
	public ClientRepair queryRepair(ClientAno clientAno) {
		// 查询当前工位的工序ID
		Integer proId = clientRepairMapper.selectProIdByStationIdAndBatchCode(clientAno.getStationId(),
				clientAno.getBatchCode());
		if (proId == null) {
			throw new QueryException("未找到维修工序！");
		}
		Boolean flag = false;
		// 查询当前批次
		Batch batch = clientBatchMapper.selectByBatchCode(clientAno.getBatchCode());
		// 查询当前所在工序
		OrderFlow orderFlow = clientOrderFlowMapper.selectByOrderFlowId(batch.getOrderFlowId());
		// 查询上道工序是否已完工，如果未完工则正常完工
		BatchFlowFinish batchFlowFinish = clientBatchFlowFinishMapper.selectByBatchIdAndSerialNum(batch.getBatchId(),
				orderFlow.getSerialNum() - 1);
		if (null != batchFlowFinish && batchFlowFinish.getOrderFlowStateId() == 2) {
			batchFlowFinish.setOrderFlowStateId(3);
			clientBatchFlowFinishMapper.updateBatchFlowFinish(batchFlowFinish);
		}
		// 判断工序相同时可以进行下一步
		if (proId == orderFlow.getProId()) {
			flag = true;
		} else if (clientAno.getIsAllowSkip()) {
			// 将当前工序跳序完工
			allowSkip(batch.getBatchId(), orderFlow, clientAno);
			// 允许跳序时查询剩下的工序
			List<OrderFlow> orderFlows = clientOrderFlowMapper.nextOrderFlowByCurrentOrderFlowId(batch.getOrderFlowId(),
					orderFlow.getOrderTechId());
			for (OrderFlow nextOrderFlow : orderFlows) {
				// 如果后面工序有相同时可以进行下一步
				if (nextOrderFlow.getProId() == proId) {
					orderFlow = nextOrderFlow;
					flag = true;
					// 更新批次表信息
					batch.setOrderFlowId(nextOrderFlow.getOrderFlowId());
					// 修改状态为已投产状态
					batch.setOrderFlowStateId(1);
					Integer count = clientBatchMapper.updateBatch(batch);
					if (count == 0) {
						throw new BusinessException("更新批次记录失败！");
					}
					break;
				} else {
					allowSkip(batch.getBatchId(), nextOrderFlow, clientAno);
				}
			}
		}
		if (flag) {
			// 当前工序序号
			Integer serialNum = orderFlow.getSerialNum();
			if (batch.getOrderFlowStateId() == 1) {
				// 扫描表示维修工序开始，第一次扫描时往报工表插入一条新记录
				BatchFlowFinish newBatchFlowFinish = new BatchFlowFinish();
				newBatchFlowFinish.setBatchId(batch.getBatchId());
				newBatchFlowFinish.setStationId(clientAno.getStationId());
				newBatchFlowFinish.setUserId(clientAno.getUserId());
				newBatchFlowFinish.setClasseId(clientAno.getClasseId());
				newBatchFlowFinish.setOrderFlowStateId(2);
				newBatchFlowFinish.setStartDate(new Date());
				newBatchFlowFinish.setSerialNum(serialNum);
				Integer count = clientBatchFlowFinishMapper.insertBatchFlowFinish(newBatchFlowFinish);
				if (count == 0) {
					throw new BusinessException("新增报工记录失败！");
				}
				Integer orderTechId = batch.getOrderTechId();
				Integer orderFlowId = clientOrderFlowMapper.selectOrderFlowIdByOrderTechId(orderTechId, serialNum);
				// 更新批次表信息
				batch.setOrderFlowId(orderFlowId);
				// 修改状态为已投产状态
				batch.setOrderFlowStateId(2);
				count = clientBatchMapper.updateBatch(batch);
				if (count == 0) {
					throw new BusinessException("更新批次记录失败！");
				}
				// 查询未完成的不良记录
				ClientAno untreatedClientAno = clientAnoMapper.queryUntreatedClientAnoId(batch.getBatchId());
				// 如果有记录且没有开始时间则更新不良记录表中开始时间
				if (untreatedClientAno != null && untreatedClientAno.getStartDate() == null) {
					// 查询托盘ID
					Integer palletId = clientPalletMapper.selectPalletIdByBatchId(batch.getBatchId());
					ClientAno startClientAno = new ClientAno();
					startClientAno.setClientAnoId(untreatedClientAno.getClientAnoId());
					startClientAno.setStartDate(new Date());
					startClientAno.setPalletId(palletId);
					startClientAno.setAnoState(2);
					clientAnoMapper.updateByPrimaryKeySelective(startClientAno);
				}
			}
		} else {
			throw new BusinessException("当前工位不能进行该单子作业！");
		}
		return clientRepairMapper.queryRepair(clientAno.getBatchCode());
	}

	/**
	 * 根据任务单ID查询全部工序
	 */
	@Override
	public List<OrderFlow> selectAllProByBatchId(Integer batchId) {
		return clientProMapper.selectAllProByBatchId(batchId);
	}

	/**
	 * 查询未进站批次
	 */
	@Override
	public List<ClientRepair> queryNoEntryBatch(BasePojo basePojo) {
		Integer pagesize = basePojo.getPagesize();
		Integer pageindex = basePojo.getPageindex();
		if (pagesize != null && pageindex != null) {
			basePojo.setIncept(pagesize * (pageindex - 1));
		}
		return clientRepairMapper.queryNoEntryBatch(basePojo);
	}

	/**
	 * 查询未进站批次数量
	 */
	@Override
	public Integer countQueryNoEntryBatch() {
		return clientRepairMapper.countQueryNoEntryBatch();
	}

	/**
	 * 查询已进站批次
	 */
	@Override
	public List<ClientRepair> queryArrivalBatch(Integer stationId) {
		return clientRepairMapper.queryArrivalBatch(stationId);
	}

	/**
	 * 维修完工
	 */
	@Override
	@Transactional
	public String repairFinish(ClientAno clientAno) {
		if (clientAno.getBatchId() == null) {
			throw new ParamsErrorException("请传入批次ID！");
		}
		// 查询批次表信息
		Batch batch = clientBatchMapper.selectByBatchId(clientAno.getBatchId());
		// 查询当前流程
		OrderFlow orderFlow = clientOrderFlowMapper.selectByOrderFlowId(batch.getOrderFlowId());
		// 完工当前工序
		BatchFlowFinish batchFlowFinish = clientBatchFlowFinishMapper.selectByBatchIdAndSerialNum(batch.getBatchId(),
				orderFlow.getSerialNum());
		if (batchFlowFinish == null) {
			throw new QueryException("未查到开工记录！");
		} else if (batchFlowFinish.getOrderFlowStateId() == 3 || batchFlowFinish.getOrderFlowStateId() == 4) {
			throw new BusinessException("该单子已完工或已跳序完工！");
		}
		batchFlowFinish.setOrderFlowStateId(3);
		batchFlowFinish.setEndDate(new Date());
		Integer count = clientBatchFlowFinishMapper.updateBatchFlowFinish(batchFlowFinish);
		if (count == 0) {
			throw new ModifyFailedException("更新报工记录失败！");
		}
		// 设置下道工序序号
		Integer nextSerialNum = orderFlow.getSerialNum() + 1;
		// 设置下道流程ID
		Integer nextOrderFlowId = clientOrderFlowMapper.selectOrderFlowIdByOrderTechId(batch.getOrderTechId(),
				nextSerialNum);
		// 情况1：没有选返回工序，并且有下道工序
		if (clientAno.getSerialNum() == null && nextOrderFlowId != null) {
			// 查询下道工序是否为正常工序
			Integer proTypeId = clientProMapper.queryNextProTypeIdByBatchId(clientAno.getBatchId());
			// 更新批次表信息
			if (proTypeId == 3) {
				updateBatch(batch, nextOrderFlowId, false, false);
			} else {
				updateBatch(batch, nextOrderFlowId, true, false);
			}
			// 情况2：没有选返回工序，并且没有下道工序
		} else if (clientAno.getSerialNum() == null && nextOrderFlowId == null) {
			// 批次完工和维修完工增加维修次数
			updateBatch(batch, null, true, true);
			// 查询已完成数量（包括自己）
			int finished = clientBatchMapper.finished(batch.getOrderId(), null);
			Order order = clientOrderMapper.selectByOrderId(batch.getOrderId());
			// 如果全部完成则修改任务单状态为完成
			if (finished == order.getPlanNum()) {
				orderMapper.updateLastExecuteState(order.getOrderId(), 5);
			}
			// 情况3：有选返回工序，并且和下道工序序号相同
		} else if (clientAno.getSerialNum() == nextSerialNum) {
			// 更新批次表信息
			updateBatch(batch, nextOrderFlowId, true, false);
			// 情况4：有选返回工序，并且和下道工序序号不相同
		} else {
			// 重新变换流程
			// 查询原工艺流程下未完成工序
			List<OrderFlow> oldOrderFlows = clientOrderFlowMapper.queryRemainProList(orderFlow.getOrderTechId(),
					orderFlow.getSerialNum());
			// 复制传入工序及以下工序
			List<OrderFlow> newOrderFlows = clientOrderFlowMapper.queryProList(orderFlow.getOrderTechId(),
					clientAno.getSerialNum() - 1);
			Integer serialNum = nextSerialNum;
			// 更改新顺序号
			for (OrderFlow newOrderFlow : newOrderFlows) {
				newOrderFlow.setSerialNum(serialNum);
				serialNum++;
			}
			// 调用工检上报不良的复制流程到原工艺流程已完工工序下面
			clientAnoServiceImpl.copyOrderFlows(newOrderFlows, orderFlow.getOrderTechId(), orderFlow.getOrderTechId());
			// 删除未完成工序
			deleteOrderFlows(oldOrderFlows);
			// 查询新的下道流程ID
			Integer newOrderFlowId = clientOrderFlowMapper.selectOrderFlowIdByOrderTechId(batch.getOrderTechId(),
					nextSerialNum);
			// 更新批次表信息
			updateBatch(batch, newOrderFlowId, true, false);
		}
		return "维修完工成功！";
	}

	/**
	 * 更新批次表
	 * 
	 * @param batch
	 * @param orderFlowId
	 * @param addRepairCount
	 */
	private void updateBatch(Batch batch, Integer orderFlowId, Boolean addRepairCount, Boolean finish) {
		if (orderFlowId != null) {
			// 设置下道流程
			batch.setOrderFlowId(orderFlowId);
			// 修改状态为已投产状态
			batch.setOrderFlowStateId(1);
		}
		if (addRepairCount) {
			// 增加维修次数
			batch.setRepairCount(batch.getRepairCount() == null ? 1 : batch.getRepairCount() + 1);
			// 增加维修完工时间
			// 查询当前批次未处理完的不良单
			ClientAno untreatedClientAno = clientAnoMapper.queryUntreatedClientAnoId(batch.getBatchId());
			ClientAno repairFinishClientAno = new ClientAno();
			repairFinishClientAno.setClientAnoId(untreatedClientAno.getClientAnoId());
			repairFinishClientAno.setEndDate(new Date());
			// 查询是否有未完成的良现象
			Integer count = clientAnoDetailMapper.queryCountByClientAnoId(untreatedClientAno.getClientAnoId());
			if (count == 0) {
				// 将不良单结束
				repairFinishClientAno.setAnoState(3);
			}
			clientAnoMapper.updateByPrimaryKeySelective(repairFinishClientAno);
		}
		if (finish) {
			// 批次完工
			batch.setProductStateId(4);
		}
		Integer count = clientBatchMapper.updateBatch(batch);
		if (count == 0) {
			throw new BusinessException("更新批次记录失败！");
		}
	}

	/**
	 * 删除流程
	 * 
	 * @param OrderFlow
	 * @return
	 */
	public void deleteOrderFlows(List<OrderFlow> orderFlows) {
		// 删除流程相关数据
		for (OrderFlow orderFlow : orderFlows) {
			Integer orderFlowId = orderFlow.getOrderFlowId();
			// 删除流程
			Integer count = clientOrderFlowMapper.deleteOrderFlowByOrderFlowId(orderFlowId);
			if (count == 0) {
				throw new ModifyFailedException("删除流程失败！");
			}
			// 删除其它关联数据
			// 1工位po_order_station
			// 删除关联工位信息
			clientOrderStationMapper.deleteOrderStationByOrderFlowId(orderFlowId);
			// 2采集参数po_order_dete
			// 删除关联采集参数信息
			clientOrderDeteMapper.deleteOrderDeteByOrderFlowId(orderFlowId);
			// 3关键物料po_order_bom
			// 删除关联关键物料信息
			clientOrderBomMapper.deleteOrderBomByOrderFlowId(orderFlowId);
			// 4不良现象po_order_badpheno
			// 删除关联不良现象信息
			clientOrderBadphenoMapper.deleteOrderBadphenoByOrderFlowId(orderFlowId);
		}
	}

	/**
	 * 跳序完工
	 * 
	 * @param batchId
	 * @param orderFlow
	 * @param clientAno
	 */
	private void allowSkip(Integer batchId, OrderFlow orderFlow, ClientAno clientAno) {
		// 查询本道工序是否已完工，如果未完工则正常完工
		BatchFlowFinish batchFlowFinish = clientBatchFlowFinishMapper.selectByBatchIdAndSerialNum(batchId,
				orderFlow.getSerialNum());
		if (null == batchFlowFinish) {
			// 将跳过的工序记录到报工表中，设为跳序完工
			BatchFlowFinish newBatchFlowFinish = new BatchFlowFinish();
			newBatchFlowFinish.setBatchId(batchId);
			newBatchFlowFinish.setProId(orderFlow.getProId());
			newBatchFlowFinish.setStationId(clientAno.getStationId());
			newBatchFlowFinish.setUserId(clientAno.getUserId());
			newBatchFlowFinish.setOrderFlowStateId(4);
			newBatchFlowFinish.setSerialNum(orderFlow.getSerialNum());
			Integer count = clientBatchFlowFinishMapper.insertBatchFlowFinish(newBatchFlowFinish);
			if (count == 0) {
				throw new BusinessException("新增报工记录失败！");
			}
		} else if (batchFlowFinish.getOrderFlowStateId() != 3) {
			batchFlowFinish.setOrderFlowStateId(4);
			clientBatchFlowFinishMapper.updateBatchFlowFinish(batchFlowFinish);
		}
	}
}
